﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;

using GameLibrary.Internal.Converters;

namespace G.Model
{
    [CollectionDataContract]
    public class GameElementDefs 
        : ICollection<GameElementDef>,
        HasGameSpaceDef
    {
        public delegate void ElementPositionChangedHandler(GameLocation location);
        public delegate void ElementHandler(GameElementDef subject);

        public event ElementHandler PropertyChangedEvent;
        public event ElementHandler ElementAddedEvent;
        public event ElementHandler ElementRemovedEvent;

        private readonly Dictionary<GameLocation, GameElementDef> _Collection;
        
        private GameSpaceDef _GameDef;
        
        public GameElementDefs()
        {
            _Collection = new Dictionary<GameLocation, GameElementDef>();
        }
        
        public GameElementDefs(GameSpaceDef pGameDef)
        {
            _GameDef = pGameDef;
            _Collection = new Dictionary<GameLocation, GameElementDef>();
        }

        [Browsable(false)]
        public GameSpaceDef GameDef
        {
            get { return _GameDef; }
            set 
            { 
                _GameDef = value; 
                foreach (GameElementDef  element in this) {
                    element.GameDef = value;
                }
            }
        }
        
        [Browsable(false)]
        public ICollection<string> PlayerNames
        {
            get
            {
                List<string> list = new List<string>();
                foreach (GameElementDef e in _Collection.Values)
                {
                    if (!list.Contains(e.Player))
                    {
                        list.Add(e.Player);
                    }
                }
                return list;
            }
        }

        [Browsable(false)]
        public Dictionary<GameLocation, GameElementDef> Dictionary
        {
            get { return _Collection; }
        }
        
        public void FireElementPropertyChanged(GameElementDef element)
        {
            if (PropertyChangedEvent != null)
            {
                PropertyChangedEvent(element);
            }
            if (_GameDef != null)
            {
                _GameDef.IsDirty = true;
            }
        }

        private bool HasName(string name)
        {
            bool result = false;
            
            foreach (GameElementDef element in this) {
                
                if (element.Name == name) {
                    result = true;
                    break;
                }
            }
            
            return result;
        }

        public int Count
        {
            get { return _Collection.Count; }
        }
        
        public bool IsReadOnly
        {
            get { return false; }
        }
        
        public void Add(GameElementDef item)
        {
            _Collection.Add(item.Location, item);
            if (ElementAddedEvent != null)
            {
                ElementAddedEvent(item);
            }
            if (item.GameDef != null)
            {
                item.GameDef.GamePlayerDefs.DeterminePlayers(item.GameDef);
            }
            if (_GameDef != null)
            {
                _GameDef.IsDirty = true;
                item.GameDef = _GameDef;
            }
        }
        
        public void Clear()
        {
            _Collection.Clear();
            _GameDef.IsDirty = true;
        }
        
        public bool Contains(GameElementDef item)
        {
            return _Collection.ContainsKey(item.Location);
        }
        
        public bool Contains(GameLocation key)
        {
            return _Collection.ContainsKey(key);
        }
        
        public void CopyTo(GameElementDef[] array, int arrayIndex)
        {
            _Collection.Values.CopyTo(array, arrayIndex);
        }
        
        public bool Remove(GameElementDef item) 
        {
            bool b = _Collection.Remove(item.Location);
            if (item.GameDef != null)
            {
                item.GameDef.GamePlayerDefs.DeterminePlayers(item.GameDef);
            }
            if (ElementRemovedEvent != null)
            {
                ElementRemovedEvent(item);
            }
            _GameDef.IsDirty = true;
            return b;
        }
        
        public IEnumerator<GameElementDef> GetEnumerator()
        {
            return _Collection.Values.GetEnumerator();
        }
        
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _Collection.Values.GetEnumerator();
        }
        
        public GameElementDef this[GameLocation key]
        {
            get
            {
                return _Collection[key];
            }
            set
            {
                _Collection[key] = value;
                _GameDef.IsDirty = true;
            }
        }
        
    }
        
}
